package com.cloud.music.aspect;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;

@Aspect
@Component
@Slf4j
public class OptionLogAspect {

    /**
     * 请求时间
     */
    ThreadLocal<Long> startTime = new ThreadLocal<>();

    /**
     * 设置操作切入点，在注解的位置切入代码
     */
    @Pointcut("@annotation(com.cloud.music.annotation.OptionLog) || @within(com.cloud.music.annotation.OptionLog)")
    public void optionTimePointCut() {
    }

    @Before("optionTimePointCut()")
    public void doBefore() {
        startTime.set(System.currentTimeMillis());
    }

    @AfterReturning(value = "optionTimePointCut()", returning = "result")
    public void doAfterReturning(JoinPoint joinPoint, Object result) {
        // 从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 获取切入点所在的方法
        Method method = signature.getMethod();
        // 获取request
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
        log.info("Request URL: {}", request.getRequestURL().toString());
        log.info("Request Method: {}", request.getMethod());
        log.info("Request IP: {}", request.getRemoteAddr());
        log.info("Request Method: {}.{}", method.getDeclaringClass().getName(), method.getName());
        log.info("Request Parameters: {}", JSON.toJSONString(joinPoint.getArgs()));
        log.info("Response Result: {}", JSON.toJSONString(result));
        log.info("Execution Time: {} milliseconds", System.currentTimeMillis() - startTime.get());
        startTime.remove();
    }
}
